package com.star.news.service.impl;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.star.news.dto.NewsPageWebDTO;
import com.star.news.dto.NewsSaveDTO;
import com.star.news.dto.NewsUpdateDTO;
import com.star.news.entity.News;
import com.star.news.entity.NewsCollect;
import com.star.news.entity.NewsContent;
import com.star.news.enums.TopType;
import com.star.news.mapper.NewsMapper;
import com.star.news.service.NewsCollectService;
import com.star.news.service.NewsContentService;
import com.star.news.service.NewsService;
import com.star.news.struct.NewsStruct;
import com.star.news.vo.NewsDetailVO;
import com.star.news.vo.NewsDetailWebVO;
import com.star.news.vo.NewsDetailWxappVO;
import com.star.news.vo.NewsVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;

/**
 * @author lintianyi
 * @version 1.0
 * @date 2024/6/21 16:00
 */
@Service
public class NewsServiceImpl extends ServiceImpl<NewsMapper, News> implements NewsService {


    @Resource
    private NewsContentService newsContentService;
    @Resource
    private NewsCollectService newsCollectService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(NewsSaveDTO dto) {
        this.check(dto, null);
        News news = NewsStruct.INSTANCE.to(dto).setId(null);
        this.save(news);
        //保存新闻内容
        NewsContent newsContent = new NewsContent();
        newsContent.setNewsId(news.getId());
        newsContent.setContent(dto.getContent());
        newsContentService.save(newsContent);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(NewsUpdateDTO dto) {
        Long id = dto.getId();
        this.check(dto, id);
        this.update(NewsStruct.INSTANCE.to(dto), Wrappers.<News>lambdaUpdate()
                .eq(News::getId, id)
                .set(News::getTitle, dto.getTitle())
                .set(News::getType, dto.getType())
                .set(News::getStarId, dto.getStarId())
                .set(News::getCoverUrl, dto.getCoverUrl())
        );
        //更新新闻内容
        newsContentService.update(Wrappers.<NewsContent>lambdaUpdate()
                .eq(NewsContent::getNewsId, id)
                .set(NewsContent::getContent, dto.getContent()));
    }

    @Override
    public void updateStatus(NewsUpdateDTO dto) {
        this.update(Wrappers.<News>lambdaUpdate()
                .eq(News::getId, dto.getId())
                .set(Objects.nonNull(dto.getPublishStatus()), News::getIsPublish, dto.getPublishStatus())
                .set(Objects.nonNull(dto.getTopStatus()), News::getIsTop, dto.getTopStatus())
        );
    }

    @Override
    public void deleteByIds(List<Long> ids) {
        this.removeByIds(ids);
    }

    @Override
    public IPage<NewsVO> page(NewsUpdateDTO dto) {
        return baseMapper.page(dto);
    }

    /**
     * 检查
     *
     * @param dto dto
     */
    private void check(NewsSaveDTO dto, Long id) {
        boolean save = id == null;
        String title = dto.getTitle();
        News news = save ? null : Assert.notNull(this.getById(id), "新闻不存在");
        if (save || !Objects.equals(news.getTitle(), title)) {
            Assert.isTrue(this.lambdaQuery().eq(News::getTitle, title).count() == 0
                    , "新闻标题已存在");
        }
    }

    @Override
    public NewsDetailVO getDetail(Long id) {
        return baseMapper.getDetail(id);
    }

    @Override
    public NewsDetailWxappVO getDetailWxapp(Long id) {
        return baseMapper.getDetailWxapp(id);
    }

    @Override
    public List<News> ListWxapp(Integer type, String title) {
        LambdaQueryWrapper<News> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Objects.nonNull(type), News::getType, type);
        queryWrapper.eq(StringUtils.isNotBlank(title), News::getTitle, title);
        return this.getBaseMapper().selectList(queryWrapper);
    }

    @Override
    public List<News> listWebTop3() {
        LambdaQueryWrapper<News> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(News::getIsTop, TopType.YES.getCode());
        queryWrapper.orderByDesc(News::getUpdateTime);
        queryWrapper.last("limit 3");
        return this.getBaseMapper().selectList(queryWrapper);
    }

    @Override
    public IPage<News> pageWeb(NewsPageWebDTO dto) {
        Page<News> page = new Page<>();
        page.setCurrent(dto.getCurrent());
        page.setSize(dto.getSize());
        LambdaQueryWrapper<News> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(News::getPublishTime);
        return this.getBaseMapper().selectPage(page, queryWrapper);
    }

    @Override
    public NewsDetailWebVO getDetailWeb(Long id) {
        NewsDetailWebVO newsDetailWebVO = baseMapper.getDetailWeb(id);
        //通过新闻id获取收藏数量
        newsDetailWebVO.setCollectCount(newsCollectService.getBaseMapper()
                .selectCount(new LambdaQueryWrapper<NewsCollect>().eq(NewsCollect::getNewsId, id)));
        return newsDetailWebVO;
    }

    @Override
    public void updatePageView(Long id) {
        NewsDetailVO newsDetailVO = this.getDetail(id);
        this.update(Wrappers.<News>lambdaUpdate()
                .eq(News::getId, id)
                .set(News::getPageView, newsDetailVO.getPageView() + 1)
        );
    }

    @Override
    public NewsVO getLatestByStarId(Long starId) {
        List<NewsVO> list = listLatestByStarId(starId, 1);
        return list.isEmpty() ? null : list.get(0);
    }

    @Override
    public List<NewsVO> listLatestByStarId(Long starId, int limit) {
        return baseMapper.listLatestByStarId(starId, limit);
    }
}
